package com.example.g5project.chat.controller;

import com.example.g5project.chat.constant.ImBaseConstant;
import com.example.g5project.chat.model.common.AccountParam;
import com.example.g5project.chat.model.dto.ChatDTO;
import com.example.g5project.chat.model.dto.ChatRecordDTO;
import com.example.g5project.chat.model.enumeration.MessageTypeEnum;
import com.example.g5project.chat.model.param.AllUnreadDetailQueryParam;
import com.example.g5project.chat.model.param.AppraiseParam;
import com.example.g5project.chat.model.param.ChatRecordListQueryParam;
import com.example.g5project.chat.model.param.CreateChatParam;
import com.example.g5project.chat.model.param.FinishChatParam;
import com.example.g5project.chat.model.param.InputingStatusParam;
import com.example.g5project.chat.model.param.MessageSetReadParam;
import com.example.g5project.chat.model.param.MessageReceiveParam;
import com.example.g5project.chat.model.param.MessageSendParam;
import com.example.g5project.chat.model.result.MessageReceiveResult;
import com.example.g5project.chat.model.result.MessageSendResult;
import com.example.g5project.chat.model.result.UnreadNumResult;
import com.example.g5project.chat.service.ChatService;
import com.example.g5project.chat.util.IMUserIdUtils;
import com.example.g5project.chat.util.JsonUtils;
import com.example.g5project.chat.util.TencentImUtils;
import com.example.g5project.customer.model.dto.CustomerDTO;
import com.example.g5project.customer.service.CustomerService;
import com.example.g5project.entity.Consultant;
import com.example.g5project.others.ResponseValue;
import com.example.g5project.service.ConsultantService;
import io.swagger.annotations.ApiOperation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/api/consulting/chat")
public class ChatController {

    @Autowired
    private TencentImUtils tencentImUtils;
    @Autowired
    private IMUserIdUtils imUserIdUtils;
    @Autowired
    private ChatService chatService;
    @Resource
    private CustomerService customerService;
    @Autowired
    private ConsultantService consultantService;

    @PostMapping("/send")
    @ApiOperation("查看消息")
    ResponseValue<MessageSendResult> sendMessage(@RequestBody @Valid MessageSendParam sendMessageParam) {
        Integer sendId = sendMessageParam.getSend().getAccountId();
        Integer receiveId = sendMessageParam.getReceive().getAccountId();
        // TODO: 账号导入
        // TODO：校验发送方、接收方记录是否存在 + 会话记录是否存在
        try {
            String sendMessageResultFromIM = tencentImUtils
                .sendMsg(sendMessageParam.getSyncOtherMachine() == null ? ImBaseConstant.SYNC_OTHER_MACHINE_YES : sendMessageParam.getSyncOtherMachine(),
                    imUserIdUtils.getIMUserId(sendMessageParam.getSend()),
                    imUserIdUtils.getIMUserId(sendMessageParam.getReceive()),
                    MessageTypeEnum.parseById(sendMessageParam.getMsgType()).getImMessageType(),
                    StringUtils.defaultString(sendMessageParam.getMsgContent()));
            Optional<MessageSendResult> optional = JsonUtils.readValue(sendMessageResultFromIM, MessageSendResult.class);
            if (!optional.isPresent()) {
                log.error("IM发送消息响应参数格式解析错误, sendMessageResultFromIM = {}", sendMessageResultFromIM);
            }
            MessageSendResult sendMessageResult = optional.get();
            if (!sendMessageResult.isRight()) {
                return ResponseValue.fail("403", "消息发送失败");
            }
            return ResponseValue.success(sendMessageResult);
        } catch (Exception e) {
            log.error("消息发送失败：", e);
            return ResponseValue.fail("403", e.getMessage());
        }
    }

    @PostMapping("/receive")
    @ApiOperation("接收消息")
    ResponseValue<MessageReceiveResult> queryMessage(@RequestBody @Valid MessageReceiveParam receiveMessageParam) {
        Integer sendId = receiveMessageParam.getSend().getAccountId();
        Integer receiveId = receiveMessageParam.getReceive().getAccountId();
        // TODO: 账号导入
        // TODO：校验发送方、接收方记录是否存在 + 会话记录是否存在
        try {
            String receiveMessageResultFromIM = tencentImUtils.adminGetRoamMsg(
                imUserIdUtils.getIMUserId(receiveMessageParam.getSend()),
                imUserIdUtils.getIMUserId(receiveMessageParam.getReceive()),
                receiveMessageParam.getCount() == null ? 0 : receiveMessageParam.getCount(),
                receiveMessageParam.getStartTime(), receiveMessageParam.getEndTime(),
                receiveMessageParam.getLastMsgKey());
            Optional<MessageReceiveResult> optional = JsonUtils.readValue(receiveMessageResultFromIM, MessageReceiveResult.class);
            if (!optional.isPresent()) {
                log.error("IM接收消息响应参数格式解析错误, receiveMessageResultFromIM = {}", receiveMessageResultFromIM);
            }
            MessageReceiveResult receiveMessageResult = optional.get();
            System.out.println(receiveMessageResult);
            if (!receiveMessageResult.isRight()) {
                return ResponseValue.fail("403", receiveMessageResult.getErrorInfo());
            }
            return ResponseValue.success(receiveMessageResult);
        } catch (Exception e) {
            log.error("接收消息失败: ", e);
            return ResponseValue.fail("403", e.getMessage());
        }
    }

    @PutMapping("/setRead")
    @ApiOperation("设置消息已读")
    ResponseValue setMessageRead(@RequestBody @Valid MessageSetReadParam messageSetReadParam) {
        Integer reportId = messageSetReadParam.getReport().getAccountId();
        Integer peerId = messageSetReadParam.getPeer().getAccountId();
        // TODO: 校验双方id是否存在
        try {
            tencentImUtils.adminSetMsgRead(imUserIdUtils.getIMUserId(messageSetReadParam.getReport()), imUserIdUtils.getIMUserId(messageSetReadParam.getPeer()));
            return ResponseValue.success(null);
        } catch (Exception e) {
            log.error("设置消息已读失败", e);
            return ResponseValue.fail("403", e.getMessage());
        }
    }

    @GetMapping("/unread/all")
    @ApiOperation("查询本账号下所有未读消息详情")
    ResponseValue<UnreadNumResult> queryAllUnreadDetail(@RequestBody @Valid AllUnreadDetailQueryParam queryParam) {
        try {
            AccountParam userAccount = queryParam.getUserAccount();
            List<String> peerAccounts = ListUtils.emptyIfNull(queryParam.getPeerAccounts()).stream()
                .map(e -> imUserIdUtils.getIMUserId(e))
                .collect(Collectors.toList());
            String result = tencentImUtils.getAllUnreadNum(imUserIdUtils.getIMUserId(userAccount), peerAccounts);
            Optional<UnreadNumResult> optional = JsonUtils.readValue(result, UnreadNumResult.class);
            if (!optional.isPresent()) {
                log.error("本账号下所有未读消息数量查询失败, result = {}", result);
            }
            UnreadNumResult unreadNumResult = optional.get();
            return ResponseValue.success(unreadNumResult);
        } catch (Exception e) {
            log.error("本账号下所有未读消息数量查询失败", e);
            return ResponseValue.fail("403", e.getMessage());
        }
    }

    @PostMapping("/inputing/set")
    @ApiOperation(value = "设置本账号正在输入中", notes = "redis")
    ResponseValue<String> setInputingStatus(@RequestBody @Valid InputingStatusParam param) {
        chatService.setInputingStatus(param);
        return ResponseValue.success("is inputing");
    }

    @GetMapping("/inputing/query")
    @ApiOperation(value = "获取对方账号正在输入中", notes = "redis")
    ResponseValue<Boolean> queryInputingStatus(@RequestBody @Valid InputingStatusParam param) {
        return ResponseValue.success(chatService.queryInputingStatus(param));
    }

    @PostMapping("/record/list")
    ResponseValue<List<ChatRecordDTO>> queryRecordList(@RequestBody ChatRecordListQueryParam queryParam) {
        List<ChatDTO> chats = chatService.queryRecordList(queryParam);
        if (CollectionUtils.isEmpty(chats)) {
            return ResponseValue.success(Collections.emptyList());
        }
        Set<Integer> callerIds = chats.stream().map(ChatDTO::getCustomerId).collect(Collectors.toSet());
        Set<Integer> counselorIds = chats.stream().map(ChatDTO::getConsultantId).collect(Collectors.toSet());
        Map<Integer, CustomerDTO> callerDTOMap = customerService.detailByIds(callerIds).stream().collect(Collectors.toMap(CustomerDTO::getId, Function.identity(), (a, b) -> a));
        Map<Integer, Consultant> integerConsultantMap = consultantService.getConsultantByIds(counselorIds).stream().collect(Collectors.toMap(Consultant::getConsultant_id, Function.identity(), (a, b) -> a));
        return ResponseValue.success(chats.stream().map(e -> new ChatRecordDTO(e, callerDTOMap.get(e.getCustomerId()), integerConsultantMap.get(e.getConsultantId()))).collect(Collectors.toList()));
    }

    @GetMapping("/record/detail")
    ResponseValue<ChatRecordDTO> queryRecordDetail(@RequestParam("chatId") Integer chatId) {
        List<ChatRecordDTO> payload = this.queryRecordList(new ChatRecordListQueryParam(chatId, 0, 1)).getPayload();
        if (CollectionUtils.isEmpty(payload)) {
            return ResponseValue.fail("403", "不存在");
        }
        return ResponseValue.success(payload.get(0));
    }

    @PostMapping("/create")
    ResponseValue<Integer> createChat(@RequestBody @Valid CreateChatParam createChatParam) {
        Integer chatId = chatService.create(createChatParam);
        return ResponseValue.success(chatId);
    }

    @PutMapping("/finish")
    ResponseValue finishChat(@RequestBody FinishChatParam finishChatParam) {
        return ResponseValue.valueOf(chatService.finish(finishChatParam));
    }

    @PutMapping("/appraise")
    ResponseValue appraiseChat(@RequestBody @Valid AppraiseParam param) {
        if (param.getGrade() == null && StringUtils.isEmpty(param.getAppraisementFromCustomer()) && StringUtils.isEmpty(param.getAppraisementCounselor())) {
            return ResponseValue.fail("403", "请求参数不可全为空");
        }
        return ResponseValue.valueOf(chatService.update(param));
    }
}
